package com.wmd.core.util;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.spire.pdf.PdfPageSize;
import com.wmd.core.enums.OrderTypeEnum;
import com.wmd.core.enums.QueryTypeEnum;
import com.wmd.core.exceptions.MyException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;


/**
 * Simple to Introduction
 *
 * @projectName:core-platform
 * @packageName:com.wmd.iot.badge.util
 * @className:MybatisPlusUtils
 * @Description:[扩展mybatisplus]
 * @Author:luyincheng
 * @CreateDate:2021/1/13 15:02
 * @blog:[方法具体上行/下行参数文档]
 */
public class MybatisPlusUtils {

    public static String PageNumName="pageNum";
    public static String PageSizeName="pageSize";
    public static boolean isHumpToLine=true;

    public static <T> Page<T> getPageFromMap(Map<String, Object> map){
        if(!map.containsKey(PageNumName)||!map.containsKey(PageSizeName)){
            throw new MyException(400,"缺少分页参数");
        }
        long page=Long.parseLong(map.get(PageNumName).toString());
        long size=Long.parseLong(map.get(PageSizeName).toString());
        map.remove(PageNumName);
        map.remove(PageSizeName);
        return new Page<T>(page,size);
    }


    private static final Log logger = LogFactory.getLog(MybatisPlusUtils.class);



    /**
     * @description:T中为要查询参数，map中是查询类型，默认为equal
     * @author: luyincheng
     * @date: 2021/1/14 16:32
     * @return:
     */
    public static <T> QueryWrapper<T> notNullField(T T, Map<String, Object> queryType, QueryWrapper<T> wrapper) {
        if (T == null) {
            return wrapper;
        }
        List<Field> fields = new ArrayList<>();
        Class<?> currentClass = T.getClass();
        while (currentClass != null) {
            final Field[] declaredFields = currentClass.getDeclaredFields();
            for (final Field field : declaredFields) {
                fields.add(field);
            }
            currentClass = currentClass.getSuperclass();
        }

        for (Field field : fields) {
            field.setAccessible(true);
            String type = "Equal";
            if (queryType != null && queryType.containsKey(field.getName() + QueryType)) {
                type = queryType.get(field.getName() + QueryType).toString();
            }

            try {
                //序列化 字段不需要查询
                if ("serialVersionUID".equals(field.getName())) {
                    continue;
                }


                //主键 注解TableId
                TableId tableId = field.getAnnotation(TableId.class);
                String databaseColumn=null;
                if (tableId != null) {
                    //主键
                    databaseColumn=tableId.value();
                    WrapperQueryType(tableId.value(), type, field.get(T), wrapper);
//                    wrapper.eq(tableId.value(),field.get(T));
                    continue;
                }else {
                    TableField tableField = field.getAnnotation(TableField.class);
                    if (tableField != null) {
                        if (tableField.exist()) {
                            databaseColumn=tableField.value();
                        }
                    }
                }
                if(!StringUtils.hasLength(databaseColumn)){
                    databaseColumn=isHumpToLine?HumpTransform.humpToLine2(field.getName()):field.getName();
                }
                if(queryType.containsKey(field.getName()+OrderType)){
                    WrapperOrderType(databaseColumn,queryType.get(field.getName()+OrderType).toString(),wrapper);
                }
                //属性为空，不用查询
                if (field.get(T) != null) {
                    WrapperQueryType(databaseColumn, type, field.get(T), wrapper);
                }
//                wrapper.eq(HumpTransform.humpToLine2(field.getName()),field.get(T));
            } catch (IllegalAccessException e) {
                logger.error(e.getMessage());
            }
        }
        return wrapper;
    }

    public static final String QueryType = "_STYPE";
    public static final String OrderType = "_ORDER";

    /**
     * @description:map中存放所有参数和查询方式
     * @author: luyincheng
     * @date: 2021/1/14 16:26
     * @return:
     */
    public static <T> QueryWrapper<T> notNullMap(Class<?> c, Map<String, Object> map, QueryWrapper<T> wrapper) {
        //Map<String,Object> specialQuery=new HashMap<>();
        //org.apache.commons.beanutils.BeanUtils.populate(obj, map);
        map.forEach((k, v) -> {
            if (k.contains(QueryType)||k.contains(OrderType) || StringUtil.isEmpty(v)) {
                return;
            }
            //特殊查询
            try {
                //验证参数有效性
                Field f = c.getDeclaredField(k);
                String databaseColumn = isHumpToLine?HumpTransform.humpToLine2(k):k;

                //数据库中字段名和实体类属性不一致 注解TableField
                TableField tableField = f.getAnnotation(TableField.class);
                if (tableField != null) {
                    if (tableField.exist()) {
                        databaseColumn=tableField.value();
//                        wrapper.eq(tableField.value(),field.get(T));
                    }// @TableField(exist = false) 不是表中内容 不形成查询条件
                }

                if (map.containsKey(k + QueryType)) {
                    WrapperQueryType(databaseColumn, map.get(k + QueryType).toString(), v, wrapper);
                } else {
                    wrapper.eq(databaseColumn, v);
                }
                if(map.containsKey(k+OrderType)){
                    WrapperOrderType(databaseColumn,map.get(k+OrderType).toString(),wrapper);
                }
            } catch (NoSuchFieldException e) {
                logger.error(e.getMessage());
            }
        });
        return wrapper;
    }
    /**
     * @description:map中存放所有参数和查询方式，且不检查key有效性
     * @author: luyincheng
     * @date: 2021年4月27日 15:00:12
     * @return:
     */
    public static <T> QueryWrapper<T> notNullMap(Map<String, Object> map, QueryWrapper<T> wrapper) {
        //Map<String,Object> specialQuery=new HashMap<>();
        //org.apache.commons.beanutils.BeanUtils.populate(obj, map);
        map.forEach((k, v) -> {
            if (k.contains(QueryType) || StringUtil.isEmpty(v)) {
                return;
            }


            String databaseColumn = isHumpToLine?HumpTransform.humpToLine2(k):k;

            //特殊查询
           if (map.containsKey(k + QueryType)) {
                WrapperQueryType(databaseColumn, map.get(k + QueryType).toString(), v, wrapper);
            } else {
                wrapper.eq(databaseColumn, v);
            }
            if(map.containsKey(k+OrderType)){
                WrapperOrderType(databaseColumn,map.get(k+OrderType).toString(),wrapper);
            }
        });
        return wrapper;
    }
    public static <T> void WrapperQueryType(String databaseColumn, String type, Object v, QueryWrapper<T> wrapper) {
        QueryTypeEnum e = QueryTypeEnum.valueOf(type);
        switch (e) {
            case Like:
                wrapper.like(databaseColumn, v);
                break;
            case Equal:
                wrapper.eq(databaseColumn, v);
                break;
            case Greater:
                wrapper.gt(databaseColumn, v);
                break;
            case GreaterEqual:
                wrapper.ge(databaseColumn, v);
                break;
            case Less:
                wrapper.lt(databaseColumn, v);
                break;
            case LessEqual:
                wrapper.le(databaseColumn, v);
                break;
            case NotEqual:
                wrapper.ne(databaseColumn, v);
                break;
            case In:
                String vi = v.toString();
                if (vi.contains(",")) {
                    String[] values=vi.split(",");
                    wrapper.in(databaseColumn, Arrays.asList(values));
                } else {
                    wrapper.eq(databaseColumn, v);
                }
                break;
            case Between:
                String value = v.toString();
                if (!value.contains(",")) {
                    wrapper.eq(databaseColumn, value);
                } else {
                    String[] b = value.split(",");
                    wrapper.between(databaseColumn, b[0], b[1]);
                }
                break;
            default:
                wrapper.eq(databaseColumn, v);
                break;
        }
    }
    public static <T> void WrapperOrderType(String databaseColumn, String type,QueryWrapper<T> wrapper) {
        OrderTypeEnum e = OrderTypeEnum.valueOf(type);
        switch (e) {
            case asc:
                wrapper.orderByAsc(databaseColumn);
                break;
            case desc:
                wrapper.orderByDesc(databaseColumn);
                break;
            default:
                wrapper.orderByAsc(databaseColumn);
                break;
        }
    }
    public static Object StringToObject(String s, Class<?> c) {
        switch (c.getName()) {
            case "java.lang.Integer":
                return Integer.parseInt(s);
            case "java.lang.String":
                return s;
            case "java.lang.Long":
                return Long.parseLong(s);
            case "java.util.Date":
                SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                try {
                    return formatter.parse(s);
                } catch (ParseException e) {
                    e.printStackTrace();
                    return null;
                }
            case "java.lang.Float":
                return Float.parseFloat(s);
            default:
                return null;
        }
    }
}
